package curtain.whynot.frame.basic.csv.controller;

import com.alibaba.fastjson.JSON;

import com.baomidou.mybatisplus.toolkit.StringUtils;

import com.whynot.frame.basic.common.model.APIBase;
import com.whynot.frame.basic.mybatis.service.BaseServiceImpl;
import com.whynot.frame.basic.mybatis.util.MybatisUtil;
import com.whynot.frame.basic.util.WebUtils;
import curtain.whynot.frame.basic.csv.CsvExport;
import curtain.whynot.frame.basic.csv.CsvImport;
import curtain.whynot.frame.basic.csv.config.CsvConfiguration;
import curtain.whynot.frame.basic.csv.config.CsvTable;
import curtain.whynot.frame.basic.csv.excle.ExcelImportImpl;
import curtain.whynot.frame.basic.csv.excle.ExcleExport;
import curtain.whynot.frame.basic.csv.impl.CsvImportImpl;
import curtain.whynot.frame.basic.csv.impl.ImportResult;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.*;

/**
 * 描    述:对hollyui的表格的增删改查，常用的方法的封装
 * 创建时间: 2018/5/17
 */
public class BaseCsvController<W extends BaseServiceImpl, T> {

    private static final Logger logger = LoggerFactory.getLogger(BaseCsvController.class);


    @Autowired
    protected W baseService;

    @Resource(name = "csvImport")
    protected CsvImport csvImport;

    @Resource(name = "csvConfig")
    protected CsvConfiguration csvConfig;

    @Resource(name = "excleImport")
    protected ExcelImportImpl excleImport;

    @Resource(name = "csvExport")
    protected CsvExport csvExport;

    @Resource(name = "excleExport")
    protected ExcleExport excleExport;


    /***
     * 描  述: sql形式导出rest方法
     * 参  数:file
     * 参  数:tableId
     * 参  数:request
     * 返回值: com.hollycrm.hollybeacons.system.web.ServiceResult
     * 创建时间: 2018/7/23
     */
    @ApiOperation(value = "通用sql的导出方法", notes = "通用的导出方法", response = APIBase.class)
    @RequestMapping(value = "/sqlexport", method = RequestMethod.POST)
    public APIBase sqlexport(
            @RequestParam String tableId,
            @RequestParam(required = false) List<Integer> options,
            @RequestParam(required = false, defaultValue = "csv") String exportType,
            @RequestParam(required = false) String sqlKey,
            @RequestParam Map<String, Object> param,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        logger.debug("查询参数 param:" + param);

//        // 1.从DB获取数据
//        try{
//            String tenantId = (String) param.get("tenantId");
//            String proId = (String) param.get("proId");
//            String userCode = (String) param.get("userCode");
//            UserInfoVo userInfo = WebUtils.getUserInfo();
//            userInfo.setTenantId(tenantId);
//            userInfo.setProId(proId);
//            userInfo.setUserCode(userCode);
//        }catch (Exception e){
//
//        }

        List<Object> list = MybatisUtil.selectByStatement(sqlKey,param);
        List<? extends CsvTable.CsvField> fields = csvConfig.getExportedCsvFields(tableId);

        fields = this.expandFields(request, fields);
        // 2.写入临时文件
        File tempDir = WebUtils.getTempDir(request.getSession().getServletContext());
        File tmpFile = null;
        if("Excle".equalsIgnoreCase(exportType)){
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".xls");
            if (options != null) {
                excleExport.expToFile(list, tableId, tmpFile, fields, options);
            } else {
                excleExport.expToFile(list, tableId, tmpFile, fields);
            }
        } else {
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".csv");
            if (options != null) {
                csvExport.expToFile(list, tableId, tmpFile, fields, options);
            } else {
                csvExport.expToFile(list, tableId, tmpFile, fields);
            }
        }
        logger.debug("生成文件存储位置:" + tmpFile.getAbsolutePath());
        // 3.下载

        ///////////////因目前没有分布式文件存储系统，暂时只完成功能，只支持单节点，等有文件系统后将文件推送到文件系统后进行下载
//      InputStream in = new FileInputStream(tmpFile);
//      WebUtils.download(response, in, tmpFile.getName());
        return createSuccessResult(tmpFile.getName());
    }


    ///调用基类统一的导入列表方法
    @ApiOperation(value = "通用的导入列表方法", notes = "通用的导入列表方法", response = APIBase.class)
    @RequestMapping(value = "/sqlimport", method = RequestMethod.POST, produces = "text/html;charset=utf-8")
    public void sqlimport(@RequestParam MultipartFile file,
                                   @RequestParam Map<String, Object> param,
                                   @RequestParam String tableId, HttpServletRequest request ,HttpServletResponse response)
            throws Exception {
        // 1.保存到临时文件中
        CsvImportImpl.setRequest(request);
        InputStream in = file.getInputStream();
        File tempDir = WebUtils.getTempDir(request.getSession().getServletContext());
        File tmpFile = null;
        ImportResult result = null;
        //获取service
        CsvImportImpl.setBaseServiceImpl(baseService);

        if(null != param && !param.isEmpty()){
            Map<String, String[]> parameterMap = request.getParameterMap();
            Set<String> keys = param.keySet();
            for(String key : keys){
                Object o = param.get(key);
                try {
                    parameterMap.put(key,new String[]{o.toString()});
                }catch (Exception e){

                }
            }
        }

        CsvImportImpl.setRequest(request);

        if(file.getOriginalFilename().contains("csv")){
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".csv");
            FileUtils.copyInputStreamToFile(in, tmpFile);
            // 2.导入到数据库中
            result = csvImport.impToDb(tmpFile, tableId);
        }else{
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".xls");
            FileUtils.copyInputStreamToFile(in, tmpFile);
            // 2.导入到数据库中
            result = excleImport.impToDb(tmpFile, tableId);
        }

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(JSON.toJSONString(createSuccessResult(result)));
        out.flush();
        out.close();

//        return createSuccessResult(result);
    }

    /////不符合导入规则的数据下载
    @ApiOperation(value = "通用的不符合导入规则的数据下载", notes = "通用的不符合导入规则的数据下载")
    @RequestMapping(value = "/invalid/download" , method = RequestMethod.GET)
    public void downloadInvalidData( @RequestParam String filename, HttpServletRequest request, HttpServletResponse response)
            throws Exception{
        ///////////////因目前没有分布式文件存储系统，暂时只完成功能，只支持单节点，等有文件系统后将文件推送到文件系统后进行下载
        File tempDir = WebUtils.getTempDir(request.getSession().getServletContext());
        File tmpFile = new File(tempDir, filename);
        WebUtils.download(response, new FileInputStream(tmpFile), filename,request);
    }


    //导入模板下载
    @ApiOperation(value = "通用的导入模板下载", notes = "通用的导入模板下载")
    @RequestMapping(value = "/template/download", method = RequestMethod.GET)
    public void downloadTemplate(@RequestParam String tableId,
                                 @RequestParam(required=false) String fileName,
                                 @RequestParam(required = false, defaultValue = "csv") String type,
                                 HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        File tempDir = WebUtils.getTempDir(request.getSession().getServletContext());
        String fileType = type.equals("csv")?".csv":".xls";
        File tmpFile = new File(tempDir, UUID.randomUUID().toString() + fileType);
        if(StringUtils.isNotEmpty(fileName)){
            tmpFile = new File(tempDir, fileName + fileType);
        }
        if(type.equals("csv")){
            csvImport.getImportTemplate(tableId, tmpFile);
        }else{
            excleImport.getImportTemplate(tableId, tmpFile);
        }

        // 2.下载
        logger.debug("生成导入模板文件存储位置:" + tmpFile.getAbsolutePath());
        InputStream in = new FileInputStream(tmpFile);

        WebUtils.download(response, in, "导入模板"+fileType,request);
    }


//    /////CSV导入向导页
//    @ApiOperation(value = "通用的CSV导入列表方法", notes = "通用的CSV导入列表方法", response = ServiceResult.class)
//    @RequestMapping(value = "/wizard/import",method = RequestMethod.GET)
//    public ServiceResult importWizard(@RequestParam String tableId,
//                             @RequestParam Map<String, Object> param,
//                             HttpServletRequest request, HttpServletResponse response)
//            throws Exception {
//        CsvTable csvTable = csvConfig.getCsvTable(tableId);
//        Assert.notNull(csvTable, tableId + "对应的csvTable配置不存在");
//        List<? extends CsvTable.CsvField> fields = csvConfig.getImportedCsvFields(tableId);
//        return createSuccessResult(fields);
//    }

    ////CSV SQL导入向导页
    @ApiOperation(value = "通用的CSV导入列表方法", notes = "通用的CSV导入列表方法", response = APIBase.class)
    @RequestMapping(value = "/wizard/sqlimport",method = RequestMethod.GET)
    public APIBase sqlImportWizard(@RequestParam String tableId,
                                @RequestParam Map<String, Object> param,
                                HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        CsvTable csvTable = csvConfig.getCsvTable(tableId);
        Assert.notNull(csvTable, tableId + "对应的csvTable配置不存在");
        List<? extends CsvTable.CsvField> fields = csvConfig.getImportedCsvFields(tableId);
        return createSuccessResult(fields);
    }

//    @ApiOperation(value = "通用的CSV导出列表方法", notes = "通用的CSV导出列表方法", response = ServiceResult.class)
//    @RequestMapping(value = "/wizard/export",method = RequestMethod.GET)
//    public ServiceResult exportWizard(@RequestParam String tableId,
//                             @RequestParam Map<String, Object> param,
//                             HttpServletRequest request, HttpServletResponse response)
//            throws Exception {
//        CsvTable csvTable = csvConfig.getCsvTable(tableId);
//        Assert.notNull(csvTable, tableId + "对应的csvTable配置不存在");
//        List<? extends CsvTable.CsvField> fields = csvConfig.getExportedCsvFields(tableId);
////        this.expandWizardFields(request,fields);
////        Object exportType = param.get("exportMode");
////        exportType = exportType == null ? "csv" : exportType;
////        request.setAttribute("exportMode", exportType);
//
//        return createSuccessResult(fields);
//    }

    @ApiOperation(value = "通用的CSV导出列表方法", notes = "通用的CSV导出列表方法", response = APIBase.class)
    @RequestMapping(value = "/wizard/sqlexport",method = RequestMethod.GET)
    public APIBase sqlexportWizard(@RequestParam String tableId,
                                @RequestParam Map<String, Object> param,
                                HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        CsvTable csvTable = csvConfig.getCsvTable(tableId);
        Assert.notNull(csvTable, tableId + "对应的csvTable配置不存在");
        List<? extends CsvTable.CsvField> fields = csvConfig.getExportedCsvFields(tableId) ;
//        this.expandWizardFields(request,fields);
//        Object exportType = param.get("exportMode");
//        exportType = exportType == null ? "csv" : exportType;
//        request.setAttribute("exportMode", exportType);
        return createSuccessResult(fields);
    }

    protected APIBase createSuccessResult(Object content) {
        APIBase apiBase = new APIBase();
        apiBase.setData(content);
        return apiBase;
    }


    protected APIBase createFailResult(String errmsg) {
        APIBase apiBase = new APIBase();
        apiBase.setMsg(errmsg);
        return apiBase;
    }

    //////子类可进行二次扩展
    protected List<? extends CsvTable.CsvField> expandFields(HttpServletRequest request, List<? extends CsvTable.CsvField> fields){
        return fields;
    }
}
